﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;

namespace WebSpiderLib
{
    public class HtmlWriter : XmlTextWriter
    {
        // Fields
        public string[] AllowedAttributes;
        public string[] AllowedTags;
        public bool FilterOutput;
        public bool ReduceConsecutiveSpace;
        public bool RemoveNewlines;
        public string ReplacementTag;

        // Methods
        public HtmlWriter(TextWriter writer)
            : base(writer)
        {
            this.FilterOutput = false;
            this.ReduceConsecutiveSpace = true;
            this.AllowedTags = new string[] { 
            "p", "b", "i", "u", "em", "big", "small", "div", "img", "span", "pre", "br", "hr", "ul", "ol", "li", 
            "del", "ins", "strong", "a", "font", "dd", "dt", "table", "td", "tr", "tbody"
         };
            this.ReplacementTag = "dd";
            this.RemoveNewlines = true;
            this.AllowedAttributes = new string[] { "href", "target", "border", "src", "align", "width", "height", "color", "size" };
        }

        public HtmlWriter(StringBuilder builder)
            : base(new StringWriter(builder))
        {
            this.FilterOutput = false;
            this.ReduceConsecutiveSpace = true;
            this.AllowedTags = new string[] { 
            "p", "b", "i", "u", "em", "big", "small", "div", "img", "span", "pre", "br", "hr", "ul", "ol", "li", 
            "del", "ins", "strong", "a", "font", "dd", "dt", "table", "td", "tr", "tbody"
         };
            this.ReplacementTag = "dd";
            this.RemoveNewlines = true;
            this.AllowedAttributes = new string[] { "href", "target", "border", "src", "align", "width", "height", "color", "size" };
        }

        public HtmlWriter(Stream stream, Encoding enc)
            : base(stream, enc)
        {
            this.FilterOutput = false;
            this.ReduceConsecutiveSpace = true;
            this.AllowedTags = new string[] { 
            "p", "b", "i", "u", "em", "big", "small", "div", "img", "span", "pre", "br", "hr", "ul", "ol", "li", 
            "del", "ins", "strong", "a", "font", "dd", "dt", "table", "td", "tr", "tbody"
         };
            this.ReplacementTag = "dd";
            this.RemoveNewlines = true;
            this.AllowedAttributes = new string[] { "href", "target", "border", "src", "align", "width", "height", "color", "size" };
        }

        public override void WriteAttributes(XmlReader reader, bool defattr)
        {
            if (!this.FilterOutput)
            {
                base.WriteAttributes(reader, defattr);
            }
            else
            {
                if (reader == null)
                {
                    throw new ArgumentNullException("reader");
                }
                if ((reader.NodeType == XmlNodeType.Element) || (reader.NodeType == XmlNodeType.XmlDeclaration))
                {
                    if (reader.MoveToFirstAttribute())
                    {
                        this.WriteAttributes(reader, defattr);
                        reader.MoveToElement();
                    }
                }
                else
                {
                    if (reader.NodeType != XmlNodeType.Attribute)
                    {
                        throw new XmlException("Xml_InvalidPosition");
                    }
                    do
                    {
                        if (defattr || !reader.IsDefault)
                        {
                            bool flag = false;
                            string localName = reader.LocalName.ToLower();
                            foreach (string str2 in this.AllowedAttributes)
                            {
                                if (str2 == localName)
                                {
                                    flag = true;
                                    break;
                                }
                            }
                            if (flag)
                            {
                                this.WriteStartAttribute(reader.Prefix, localName, reader.NamespaceURI);
                            }
                            while (reader.ReadAttributeValue())
                            {
                                if (reader.NodeType == XmlNodeType.EntityReference)
                                {
                                    if (flag)
                                    {
                                        this.WriteEntityRef(reader.Name);
                                    }
                                }
                                else if (flag)
                                {
                                    this.WriteString(reader.Value);
                                }
                            }
                            if (flag)
                            {
                                this.WriteEndAttribute();
                            }
                        }
                    }
                    while (reader.MoveToNextAttribute());
                }
            }
        }

        public override void WriteComment(string text)
        {
            if (!this.FilterOutput)
            {
                base.WriteComment(text);
            }
        }

        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            if (this.FilterOutput)
            {
                bool flag = false;
                string str = localName.ToLower();
                foreach (string str2 in this.AllowedTags)
                {
                    if (str2 == str)
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    localName = "dd";
                }
            }
            base.WriteStartElement(prefix, localName, ns);
        }

        public override void WriteString(string text)
        {
            text = text.Replace("\x00a0", "&nbsp;");
            text = text.Replace("<![CDATA[", "");
            text = text.Replace("]]>", "");
            text = text.Replace("<", "&lt;");
            text = text.Replace(">", "&gt;");
            text = text.Replace("'", "&apos;");
            text = text.Replace("\"", "&quote;");
            if (this.FilterOutput)
            {
                text = text.Trim();
                if (this.ReduceConsecutiveSpace)
                {
                    text = text.Replace("&nbsp;&nbsp;&nbsp;", "&nbsp;");
                }
                if (this.RemoveNewlines)
                {
                    text = text.Replace(Environment.NewLine, " ");
                }
                base.WriteRaw(text);
            }
            else
            {
                base.WriteRaw(text);
            }
        }

        public override void WriteWhitespace(string ws)
        {
            if (!this.FilterOutput)
            {
                base.WriteWhitespace(ws);
            }
        }
    }


}
